package de.akabahn.ebd.stw.zdxfc.prs.fst.impair;

import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT0;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.FAHRSTRASSE_FD;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.GLEIS_2TER;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_C1;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_TASTE_FD;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.SIGNAL_C1;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.SIGNAL_CV14;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.VERSCHLUSS;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.WEICHE_3;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.WEICHE_4;
import de.akabahn.ebd.comm.dbd.DBDParameter;
import de.akabahn.ebd.dbd.SwitchPosition;
import de.akabahn.ebd.dbd.impl.DBDSignalF;
import de.akabahn.ebd.stw.zdxfc.prs.ZDXFCMain;
import de.akabahn.ebd.stw.zdxfc.prs.fst.FahrStrasse;

/**
 * Fahrstrasse <code>FD</code><br>
 * Start: Signal C1<br>
 * Ziel: Gleis 2TER<br>
 * <br>
 * Fahrstrassen Weichen:<br>
 * <ol>
 * <li>Weiche 3, Linkslage (Flankenschutz)</li>
 * <li>Weiche 4, Linkslage</li>
 * </ol>
 * <br>
 * Fahrstrassen Gleise:<br>
 * <ol>
 * <li>Gleis 2ter (Zielgleis, darf besetzt sein)</li>
 * </ol>
 * <br>
 * Fahrstrassen Signale:<br>
 * <ol>
 * <li>Signal C1, Startsignal, kein manueller Haltfall</li>
 * <li>Signal Cv14, Lichtschutz</li>
 * </ol>
 * 
 * @author Peter Eimann
 * @since 1.0
 * @version 1.2
 */
public class FahrStrasseFD extends FahrStrasse {

	/**
	 * Initialisierung mit ID <code>FD</code> und DBD-Name des Tastenmelders <code>S31TFDS</code>
	 * 
	 * @param main Referenz auf die Hauptklasse
	 */
	public FahrStrasseFD(ZDXFCMain main) {
		super(FAHRSTRASSE_FD, MELDER_TASTE_FD, main, SIGNAL_C1);

		fstWeichen = new FstWeiche[] {
				new FstWeiche(WEICHE_3, SwitchPosition.LEFT, true),
				new FstWeiche(WEICHE_4, SwitchPosition.LEFT, false)
		};
		
		fstGleise = new FstGleis[] {
				new FstGleis(GLEIS_2TER, false)
		};
		
		fstSignale = new FstSignal[] {
				new FstSignal(SIGNAL_C1, true),
				new FstSignal(SIGNAL_CV14, false)
		};
	}

	/**
	 * Wird die Fahrstrasse verschlossen, wird der Verschlussmelder des Signals mit Dauerlicht ausgeleuchtet,
	 * anderenfalls wird die Ausleuchtung geloescht.
	 */
	@Override
	public void setVerschlossen(boolean verschlossen) {
		super.setVerschlossen(verschlossen);

		if (verschlossen) {
			main.getDbd().set(MELDER_SIGNAL_C1[VERSCHLUSS], BIT0);
		} else {
			main.getDbd().set(MELDER_SIGNAL_C1[VERSCHLUSS], 0);
		}
	}

	/**
	 * Verschluss:<br>
	 * <ul>
	 * <li>Sofortiger Verschluss der Fahrstrasse (EPa)</li>
	 * </ul>
	 * <br>
	 * Startsignal C1:<br>
	 * <ul>
	 * <li>Fahrstrassen-ID <code>FD</code></li>
	 * <li>Signalbegriff <code>M</code></li>
	 * </ul>
	 */
	@Override
	public void einstellenProcess() {
		setVerschlossen(true);

		main.getSignal(SIGNAL_C1).setFahrStrassenId(id);
		main.getSignal(SIGNAL_C1).stellen(DBDSignalF.M);
	}

	/**
	 * Ueberpruefte Bedingungen:<br>
	 * <ol>
	 * <li>Aufloesezeit muss kleiner gleich 0 sein</li>
	 * <li>Haltfall Signal <code>C1</code></li>
	 * </ol>
	 * <br>
	 * Aktionen bei erfolgreicher Pruefung:<br>
	 * <ul>
	 * <li><i>keine</i></li>
	 * </ul>
	 */
	@Override
	public boolean aufloeseBedinungenOk() {
		return main.getSignal(SIGNAL_C1).isHalt() && getAufloeseZeit() <= 0;
	}

	/**
	 * Ueberwachte Elemente:<br>
	 * <ol>
	 * <li>Weiche 4</li>
	 * <li>Gleis 2TER</li>
	 * </ol>
	 */
	@Override
	public void onChangeBesetzung(DBDParameter dbd) {
		if (dbd.getId().equals(WEICHE_4)) {
			onChangeWeiche4();
		} else if (dbd.getId().equals(GLEIS_2TER)) {
			onChangeGleis2TER();
		}
	}

	/**
	 * Ueberwachung der Weiche 4:<br>
	 * Aktionen beim Besetzen:<br>
	 * <ol>
	 * <li>Aufloesung Weiche 4 vorbereiten</li>
	 * <li>Haltfall Startsignale</li>
	 * </ol>
	 * <br>
	 * Aktionen beim Freifahren:<br>
	 * <ol>
	 * <li>Verschluss der Fahrstrasse aufloesen</li>
	 * <li>Fahrstrasse und <code>Gleis 2TER</code> inaktiv setzen</li>
	 * <li>Ausleuchtung Tastenmelder der Fahrstrasse loeschen</li>
	 * <li>Flankenschutz <code>Weiche 3</code> aufloesen</li>
	 * <li>Weiche 4 inaktiv setzen</li>
	 * </ol>
	 */
	private void onChangeWeiche4() {
		if (main.getWeiche(WEICHE_4).isBesetzt()) {
			main.getWeiche(WEICHE_4).setAufloesenVorbereiten(true);
			haltfallStartsignale();
		} else {
			if (main.getWeiche(WEICHE_4).isAufloesenVorbereiten()) {
				main.getWeiche(WEICHE_4).setAufloesenVorbereiten(false);
				main.getWeiche(WEICHE_4).setAktiv(false);
				setVerschlossen(false);
				setAktiv(false);
				main.getGleis(GLEIS_2TER).setAktiv(false);
				main.getDbd().set(getTastenMelderId(), 0);
				main.getWeiche(WEICHE_3).setFlankenSchutz(false);
			}
		}
	}

	/**
	 * Ueberwachung des Gleises 2TER:<br>
	 * Aktionen beim Besetzen:<br>
	 * <ol>
	 * <li>Haltfall Startsignale</li>
	 * </ol>
	 * <br>
	 * Aktionen beim Freifahren:<br>
	 * <ul>
	 * <li><i>keine</i></li>
	 * </ul> 
	 */
	private void onChangeGleis2TER() {
		if (main.getGleis(GLEIS_2TER).isBesetzt()) {
			haltfallStartsignale();
		}
	}
}
